﻿using DataAccess;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace Busness
{
    class waitProcessData
    {
        public uint id = 0;
        public BaseParamter param = null;
        public waitProcessData(uint _id, BaseParamter _parm)
        {
            id = _id;
            param = _parm;
        }
    }
    public delegate void threadHandleDelegate(object key);//处理接收数据事件的方法类型
    /// <summary>
    /// 先创建一些线程，先让他们挂起，然后规定好每个线程处理的最大数据连接数，然后将
    /// 对数据库的请求分入这些线程,没有数据处理了就挂起线程，新数据来了再唤醒线程
    /// </summary>
    public class ThreadPool
    {
        private uint CurrentThreadId = 0;
        private Dictionary<uint, MyThread> threadpool = new Dictionary<uint, MyThread>();
        private List<uint> SuspendList = new List<uint>();
        private List<waitProcessData> waitDataList = new List<waitProcessData>();
        private static ThreadPool threadIns = new ThreadPool();
        private uint CurrentInsertThreadID = 1;
        public  uint MaxLinkNumber = 1000; //每个线程最多处理用户请求数量
        public uint OpenThreadNumber
        {
            set;
            get;
        }
        private ThreadPool()
        {

        }

        public void Creates(uint maxNumber)
        {
            OpenThreadNumber = maxNumber;
            for (int i = 0; i < maxNumber; i++)
            {
                NewThread();
                threadpool[CurrentThreadId].Suspend();
                SuspendList.Add((uint)i);
            }
        }
        public void ManageThread()
        {
            // 处理线程
            foreach (KeyValuePair<uint, MyThread> thread in threadpool)
            {
                if (thread.Value.userDataQuaryMap.Count == 0)
                {
                    thread.Value.Suspend();
                    SuspendList.Add(thread.Key);
                }
            }
            // 处理等待数据
            foreach (waitProcessData data in waitDataList)
            {
                HandleDataLink(data.id, data.param);
            }

        }

        public void HandleDataLink(UInt32 uid, BaseParamter param)
        {
            bool hasThreadCanProcess = false;
            foreach (KeyValuePair<uint, MyThread> p in threadpool)
            {
                if (p.Value.userDataQuaryMap.ContainsKey(uid))
                {
                    // 有一个线程在处理这个用户 ，为了防止读写死锁，把这个请求放到这个线程里面
                    hasThreadCanProcess = true;
                    p.Value.InsertUserLink(uid, param);
                }
                else if (p.Value.CurrentLinkNumber < MaxLinkNumber)
                {
                    // 有一个线程处理的用户数目小于设定的数目
                    hasThreadCanProcess = true;
                    p.Value.InsertUserLink(uid, param);
                }
            }
            if (hasThreadCanProcess == false)
            {
                // 当前线程池中没有线程能处理， 如果线程数目已经等于最大线程数，要把这个请求放入等待队列，否则新建线程处理
                if (SuspendList.Count == 0)
                {
                    waitDataList.Add(new waitProcessData(uid, param));
                }
                else
                {
                    MyThread thread = NewThread();
                    thread.InsertUserLink(uid, param);
                    thread.Resume();
                }
            }
        }

        public Dictionary<uint, MyThread> GetThreadPool()
        {
            return threadpool;
        }
        public static ThreadPool GetInstance()
        {
            return threadIns;
        }
        public MyThread GetThreadByID(uint id)
        {
            if (threadpool.ContainsKey(id))
            {
                return threadpool[id];
            }
            return null;
        }

        public void AbortAllThread()
        {
            foreach (KeyValuePair<uint, MyThread> p in threadpool)
            {
                p.Value.ExitApplation = true;
            }
        }
        public void AbortThread(uint id)
        {
            if (threadpool.ContainsKey(id))
            {
                MyThread th = threadpool[id];
                threadpool.Remove(id);
                th.Abort();
            }
        }
        public MyThread NewThread()
        {
            MyThread mThread = null;
            if (SuspendList.Count > 0 && threadpool.Count == OpenThreadNumber)
            {// 线程创建完毕后 新建线程从休眠队列里面启用
                uint threadID = SuspendList[0];
                mThread = threadpool[threadID];
                SuspendList.RemoveAt(0);
            }
            else
            {
                uint threadID = (uint)threadpool.Count;
                mThread = new MyThread(threadID);
                threadpool[threadID] = mThread;
            }
            return mThread;
        }

    }

    public class MyThread
    {
        public bool Lock
        {
            set;
            get;
        }
        public bool ExitApplation = false;
        public event threadHandleDelegate ThreadEvent; //接收数据的事件
        private Thread thread;
        public Dictionary<UInt32, DataLinkPool> userDataQuaryMap = new Dictionary<UInt32, DataLinkPool>();
        private bool bSuspend = false;
        public bool GetThreadIsSuspend()
        {
            return bSuspend;
        }
        public void InsertUserLink(uint id, BaseParamter param)
        {
            if (!userDataQuaryMap.ContainsKey(id))
            {
                DataLinkPool pool = new DataLinkPool();
                pool.AddCommandInPool(id, param);
                userDataQuaryMap.Add(id, pool);
            }
            else
            {
                userDataQuaryMap[id].AddCommandInPool(id, param);
            }
        }
        public bool RemoveUser(uint uId)
        {
            
            return true;
        }

        public int CurrentLinkNumber
        {
            get
            {
                return userDataQuaryMap.Count;
            }
        }
        private uint threadID;
        public uint ThreadID
        {
            set { threadID = value; }
            get { return threadID; }
        }
        public MyThread(uint id)
        {
            ThreadID = id;
            thread = new Thread(new ParameterizedThreadStart(HandeNewThread)); //这个线程处理接收的数据
            
            thread.Name = id.ToString();//设置线程的名字  
            thread.IsBackground = false;
            thread.Start(id);
            Console.WriteLine("开启数据库读写线程 ID = " + thread.ManagedThreadId);
        }
        public void Abort()
        {
            if (thread != null)
            {
                thread.Abort();
            }
        }

        public void Resume()
        {
            thread.Resume();
            bSuspend = false;
            Console.WriteLine("线程 ID = " + thread.ManagedThreadId + "被唤醒");
        }

        public void Suspend()
        {
            thread.Suspend();
            Console.WriteLine("线程 ID = " + thread.ManagedThreadId + "进入休眠状态");
            bSuspend = true;
        }
        void HandeNewThread(object sender)
        {
            while (!ExitApplation)
            {
                try
                {
                    foreach (KeyValuePair<uint, DataLinkPool> pool in userDataQuaryMap)
                    {
                        pool.Value.ExcutePoolCommand();
                    }
                    userDataQuaryMap.Clear();
                }
                catch
                {
                    Console.WriteLine("存储过程调用失败");
                }
                Thread.Sleep(1);
            }
            thread.Abort();
        }
    }
}
